<?php

declare (strict_types = 1);

namespace wuwu\cosydevtool\command\addons;

use Phinx\Db\Adapter\AdapterFactory;
use Phinx\Db\Adapter\ProxyAdapter;
use Phinx\Migration\MigrationInterface;
use Phinx\Util\Util;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
use think\migration\command\Migrate;

class Update extends Migrate
{
    protected function configure()
    {
        // 指令配置
        $this->setName('cosy:update')
            ->addArgument('name', Argument::OPTIONAL, "your addons name")
            ->addArgument('version', Argument::OPTIONAL, "your addons version")
            ->setDescription('Update addons');

//        $this->
    }

    protected function execute(Input $input, Output $output)
    {
//        $phpFiles = glob($this->getPath() . DIRECTORY_SEPARATOR . '*.php', defined('GLOB_BRACE') ? GLOB_BRACE : 0);
//        // filter the files to only get the ones that match our naming scheme
//        $fileNames = [];
//        /** @var Migrator[] $versions */
//        $versions = [];
//        foreach ($phpFiles as $filePath) {
//            $version = Util::getVersionFromFileName(basename($filePath));
//            $class = Util::mapFileNameToClassName(basename($filePath));
//            $fileNames[$class] = basename($filePath);
//            require_once $filePath;
//            if (!class_exists($class)) {
//                throw new \InvalidArgumentException(sprintf('Could not find class "%s" in file "%s"', $class, $filePath));
//            }
//            $migration = new $class($version, $this->input, $this->output);
//            if (!($migration instanceof AbstractMigration)) {
//                throw new \InvalidArgumentException(sprintf('The class "%s" in file "%s" must extend \Phinx\Migration\AbstractMigration', $class, $filePath));
//            }
//            $versions[$version] = $migration;
//        }
//        ksort($versions);
//        var_dump($phpFiles);
        $addonsName = $input->getArgument('name');
        $version = $input->getArgument('version');
        $info = get_addons_info($addonsName);


        $filePath = $this->app->getRootPath() . 'addons' . DIRECTORY_SEPARATOR . $addonsName . DIRECTORY_SEPARATOR . 'database'. DIRECTORY_SEPARATOR . $info['date'] . '_upgrade.php';
//        $time = Util::getVersionFromFileName(basename($filePath));
        $class = Util::mapFileNameToClassName(basename($filePath));
        $fileNames[$class] = basename($filePath);

        require_once $filePath;
        $migration = new $class($version, $this->input, $this->output);
//        $this->output->writeln(BaseJson::encode($migration->versions));
//        return;

        $this->executeMigration($migration, MigrationInterface::UP);
//        $output->writeln($class);
    }

    protected function getPath()
    {
        return $this->app->getRootPath() . 'database' . DIRECTORY_SEPARATOR . 'migrations';
    }

    protected function executeMigration(MigrationInterface $migration, $direction = MigrationInterface::UP)
    {
//        $this->output->writeln('');
//        $this->output->writeln(' ==' . ' <info>' . $migration->getVersion() . ' ' . $migration->getName() . ':</info>' . ' <comment>' . (MigrationInterface::UP === $direction ? 'migrating' : 'reverting') . '</comment>');

        // Execute the migration and log the time elapsed.
        $start = microtime(true);
        $version = $migration->getVersion();
        $startTime = time();
        $direction = (MigrationInterface::UP === $direction) ? MigrationInterface::UP : MigrationInterface::DOWN;
        $migration->setAdapter($this->getAdapter());

        // begin the transaction if the adapter supports it
        if ($this->getAdapter()->hasTransactions()) {
            $this->getAdapter()->beginTransaction();
        }

        // Run the migration
        if (method_exists($migration, MigrationInterface::CHANGE)) {
            if (MigrationInterface::DOWN === $direction) {
                // Create an instance of the ProxyAdapter so we can record all
                // of the migration commands for reverse playback
                /** @var ProxyAdapter $proxyAdapter */
                $proxyAdapter = AdapterFactory::instance()->getWrapper('proxy', $this->getAdapter());
                $migration->setAdapter($proxyAdapter);
                /** @noinspection PhpUndefinedMethodInspection */
                $migration->change();
                $proxyAdapter->executeInvertedCommands();
                $migration->setAdapter($this->getAdapter());
            } else {
                /** @noinspection PhpUndefinedMethodInspection */
                $migration->change($version);
            }
        } else {
            $migration->{$direction}();
        }

        // commit the transaction if the adapter supports it
//        if ($this->getAdapter()->hasTransactions()) {
//            $this->getAdapter()->commitTransaction();
//        }

        // Record it in the database
//        $this->getAdapter()
//            ->migrated($migration, $direction, date('Y-m-d H:i:s', $startTime), date('Y-m-d H:i:s', time()));

        $end = microtime(true);
        $data['version'] = $migration->getVersion();
        $data['class'] = $migration->getName();
        $data['time'] = sprintf('%.4fs', $end - $start);
        $data['path'] = $this->app->getRootPath();
//        $this->output->writeln(' ==' . ' <info>' . $migration->getVersion() . ' ' . $migration->getName() . ':</info>' . ' <comment>' . (MigrationInterface::UP === $direction ? 'migrated' : 'reverted') . ' ' . sprintf('%.4fs', $end - $start) . '</comment>');
        $this->output->writeln(json_encode($data));
    }
}